import 'dart:io';

import 'package:bai_le_men_im/cmomon/global.dart';
import 'package:bai_le_men_im/cmomon/utils.dart';
import 'package:bai_le_men_im/conversation/groupMessagesPage.dart';
import 'package:flutter/material.dart';
import 'package:overlay_support/overlay_support.dart';
import '../models/index.dart';
import 'package:flutter_wildfire/flutter_wildfire.dart';
import '../modal/contacts.dart' show Contact, ContactsPageData;
import '../constants.dart' show AppColors, AppStyles, Constants, Routes;
import 'dart:typed_data';

import 'dart:async';
import 'package:flutter/services.dart' show rootBundle;
import 'package:path_provider/path_provider.dart';

class _ContactItem extends StatelessWidget {
  _ContactItem(
      {@required this.avatar,
      @required this.title,
      this.groupTitle,
      this.onPressed,
      this.disabled = false,
      this.choosed,
      this.unReadCount = 0});

  final String avatar;
  final String title;
  final String groupTitle;
  final VoidCallback onPressed;
  final int unReadCount;
  final bool disabled;
  final bool choosed;

  static const VERTICAL_PADDING = 12.0;
  static const HORIZONTAL_PADDING = 18.0;
  static const UN_READ_MSG_CIRCLE_SIZE = 20.0;
  static const UN_READ_MSG_DOT_SIZE = 12.0;

  static const double MARGIN_VERTICAL = 8.0;
  static const double MARGIN_HORIZONTAL = 16.0;
  static const double GROUP_TITLE_HEIGHT = 34.0;

  bool get _isAvatarFromNet {
    return this.avatar.startsWith('http') || this.avatar.startsWith('https');
  }

  static double _height(bool hasGroupTitle) {
    final _buttonHeight = MARGIN_VERTICAL * 2 +
        Constants.ContactAvatarSize +
        Constants.DividerWidth;
    if (hasGroupTitle) {
      return _buttonHeight + GROUP_TITLE_HEIGHT;
    }
    return _buttonHeight;
  }

  @override
  Widget build(BuildContext context) {
    // 左边的图标
    Widget _avatarIcon;
    if (_isAvatarFromNet) {
      _avatarIcon = Image.network(
        avatar,
        width: Constants.ContactAvatarSize,
        height: Constants.ContactAvatarSize,
        fit: BoxFit.cover,
      );
    } else {
      _avatarIcon = Image.asset(
        avatar,
        width: Constants.ContactAvatarSize,
        height: Constants.ContactAvatarSize,
        fit: BoxFit.cover,
      );
    }
    _avatarIcon = ClipRRect(
        borderRadius: BorderRadius.circular(Constants.AvatarRadius),
        child: _avatarIcon);
    Widget avatarContainer;
    if (unReadCount > 0) {
      // 未读消息角标
      Widget unreadMsgCountText;

      unreadMsgCountText = Container(
        width: UN_READ_MSG_CIRCLE_SIZE,
        height: UN_READ_MSG_CIRCLE_SIZE,
        alignment: Alignment.center,
        decoration: BoxDecoration(
          borderRadius: BorderRadius.circular(UN_READ_MSG_CIRCLE_SIZE / 2.0),
          color: Color(AppColors.NotifyDotBg),
        ),
        child: Text(unReadCount.toString(),
            style: AppStyles.UnreadMsgCountDotStyle),
      );

      avatarContainer = Stack(
        overflow: Overflow.visible,
        children: <Widget>[
          _avatarIcon,
          Positioned(
            right: -6.0,
            top: -6.0,
            child: unreadMsgCountText,
          )
        ],
      );
    } else {
      avatarContainer = _avatarIcon;
    }
    _avatarIcon = avatarContainer;

    // 列表项主体部分
    Widget _button = Container(
      margin: const EdgeInsets.only(left: MARGIN_HORIZONTAL / 2),
      child: Opacity(
        opacity: disabled ? 0.3 : 1.0,
        child: Row(
          children: <Widget>[
            disabled
                ? Icon(
                    Icons.panorama_fish_eye,
                    color: Colors.grey,
                    size: 30.0,
                  )
                : (choosed
                    ? Icon(
                        Icons.check_circle,
                        color: Colors.green,
                        size: 30.0,
                      )
                    : Icon(
                        Icons.panorama_fish_eye,
                        color: Colors.grey,
                        size: 30.0,
                      )),
            SizedBox(width: 16.0),
            _avatarIcon,
            SizedBox(width: 16.0),
            Expanded(
              child: Container(
                padding: const EdgeInsets.only(right: MARGIN_HORIZONTAL),
                height: _ContactItem._height(false),
                alignment: Alignment.centerLeft,
                decoration: BoxDecoration(
                  border: Border(
                    bottom: BorderSide(
                        width: Constants.DividerWidth,
                        color: const Color(AppColors.DividerColor)),
                  ),
                ),
                child: Text(title, style: AppStyles.TitleStyle, maxLines: 1),
              ),
            ),
          ],
        ),
      ),
    );

    // 分组标签
    Widget _itemBody;
    if (this.groupTitle != null) {
      _itemBody = Column(
        children: <Widget>[
          Container(
            height: GROUP_TITLE_HEIGHT,
            padding: EdgeInsets.only(left: 16.0, right: 16.0),
            color: const Color(AppColors.ContactGroupTitleBg),
            alignment: Alignment.centerLeft,
            child:
                Text(this.groupTitle, style: AppStyles.GroupTitleItemTextStyle),
          ),
          _button,
        ],
      );
    } else {
      _itemBody = _button;
    }
    return InkWell(
      onTap: onPressed,
      child: _itemBody,
    );
  }
}

const INDEX_BAR_WORDS = [
  "↑",
  "☆",
  "A",
  "B",
  "C",
  "D",
  "E",
  "F",
  "G",
  "H",
  "I",
  "J",
  "K",
  "L",
  "M",
  "N",
  "O",
  "P",
  "Q",
  "R",
  "S",
  "T",
  "U",
  "V",
  "W",
  "X",
  "Y",
  "Z"
];

class ChooseFriendPage extends StatefulWidget {
  final List<User> choosedUsers;
  final List<User> excludeUsers;
  final Group group;
  ChooseFriendPage(
      {this.choosedUsers = const [], this.excludeUsers = const [], this.group});

  Color _indexBarBg = Colors.transparent;
  String _currentLetter = '';
  @override
  _ChooseFriendPageState createState() => _ChooseFriendPageState();
}

class _ChooseFriendPageState extends State<ChooseFriendPage> {
  final List<Contact> _contacts = [];
  ScrollController _scrollController;
  bool isInitialized = false; // 是否已经初始化了（是否已经请求过数据）
  List<_ContactItem> _functionButtons = [];
  final Map _letterPosMap = {INDEX_BAR_WORDS[0]: 0.0};
  int unreadFriendRequestStatus = 0;
  List<User> chooedUser = [];

  getMyfriends() async {
    try {
      var friendList = await FlutterWildfire.getMyFriendListInfo(false);
      List friendUserList = [];
      chooedUser = [];
      // chooedUser.addAll(widget.excludeUsers.toList());
      // chooedUser.addAll(widget.choosedUsers.toList());
      if (friendList.length > 0 &&
          widget.excludeUsers != null &&
          widget.excludeUsers.length > 0) {
        // 过滤掉要排除的用户
        for (var friendMap in friendList) {
          if (!widget.excludeUsers
              .any((user) => user.uid == friendMap['uid'])) {
            friendUserList.add(friendMap);
          }
        }
      }
      _contacts
        ..addAll(List.generate(friendList.length, (index) {
          var _userMap = friendList[index];
          bool _disabled = false;
          if (widget.excludeUsers != null && widget.excludeUsers.length > 0) {
            if (widget.excludeUsers
                .any((user) => user.uid == _userMap['uid'])) {
              _disabled = true;
            }
          }
          return Contact(
            disabled: _disabled,
            user: User.fromJson(friendList[index]),
            avatar: friendList[index]['portrait'],
            name: friendList[index]['displayName'],
            nameIndex:
                friendList[index]['displayName'].toString().substring(0, 1),
          );
        }));
      _contacts
          .sort((Contact a, Contact b) => a.nameIndex.compareTo(b.nameIndex));
      _scrollController = new ScrollController();
      // 计算用于 IndexBar 进行定位的关键通讯录列表项的位置
      var _totalPos = _functionButtons.length * _ContactItem._height(false);
      for (int i = 0; i < _contacts.length; i++) {
        bool _hasGroupTitle = true;
        if (i > 0 &&
            _contacts[i].nameIndex.compareTo(_contacts[i - 1].nameIndex) == 0) {
          _hasGroupTitle = false;
        }
        if (_hasGroupTitle) {
          _letterPosMap[_contacts[i].nameIndex] = _totalPos;
        }
        _totalPos += _ContactItem._height(_hasGroupTitle);
      }
      setState(() {});
    } catch (e) {
      print(e);
    }
  }

  @override
  void initState() {
    getMyfriends();
    // keywordController.addListener(keywordControllerChangedHandler);
    super.initState();
  }

  @override
  void dispose() {
    print('add friend to conversation page didChangeDependencies');
    _scrollController.dispose();
    super.dispose();
  }

  String _getLetter(BuildContext context, double tileHeight, Offset globalPos) {
    RenderBox _box = context.findRenderObject();
    var local = _box.globalToLocal(globalPos);
    int index = (local.dy ~/ tileHeight).clamp(0, INDEX_BAR_WORDS.length - 1);
    return INDEX_BAR_WORDS[index];
  }

  void _jumpToIndex(String letter) {
    if (_letterPosMap.isNotEmpty) {
      final _pos = _letterPosMap[letter];
      if (_pos != null) {
        _scrollController.animateTo(_pos,
            curve: Curves.easeOut, duration: Duration(milliseconds: 200));
      }
    }
  }

  Widget _buildIndexBar(BuildContext context, BoxConstraints constraints) {
    final List<Widget> _letters = INDEX_BAR_WORDS.map((String word) {
      return Expanded(
        child: Text(word),
      );
    }).toList();

    final double _totalHeight = constraints.biggest.height;
    final double _tileHeight = _totalHeight / _letters.length;
    return GestureDetector(
      onVerticalDragDown: (DragDownDetails details) {
        setState(() {
          widget._indexBarBg = Colors.black26;
          widget._currentLetter =
              _getLetter(context, _tileHeight, details.globalPosition);
          _jumpToIndex(widget._currentLetter);
        });
      },
      onVerticalDragEnd: (DragEndDetails details) {
        setState(() {
          widget._indexBarBg = Colors.transparent;
          widget._currentLetter = null;
        });
      },
      onVerticalDragCancel: () {
        setState(() {
          widget._indexBarBg = Colors.transparent;
          widget._currentLetter = null;
        });
      },
      onVerticalDragUpdate: (DragUpdateDetails details) {
        setState(() {
          widget._indexBarBg = Colors.black26;
          widget._currentLetter =
              _getLetter(context, _tileHeight, details.globalPosition);
          _jumpToIndex(widget._currentLetter);
        });
      },
      child: Column(
        children: _letters,
      ),
    );
  }

//write to app path
  Future<File> writeToFile(ByteData data, String path) async {
    final buffer = data.buffer;
    File file = new File(path);
    await file.writeAsBytes(
        buffer.asUint8List(data.offsetInBytes, data.lengthInBytes));
    return file;
  }

  Future<File> getImageFileFromAssets(String path) async {
    var bytes = await rootBundle.load(path);
    String dir = (await getApplicationDocumentsDirectory()).path;
    List _tmpArr = path.split('/');
    String fileName = _tmpArr.reversed.toList()[0];
    return await writeToFile(bytes, '$dir/$fileName');
  }

  addGroupMembers() async {
    List<String> userIds = chooedUser.map((user) => user.uid).toList();
    await FlutterWildfire.addGroupMembers(widget.group.target, userIds, [0]);
    widget.excludeUsers.addAll(chooedUser);
    widget.group.memberCount += chooedUser.length;
    Navigator.of(context).pop();
    // Navigator.of(context).pop();
  }

  createGroup() async {
    String groupName = "";
    List<User> _chooedUser = [];

    _chooedUser.addAll(widget.excludeUsers.toList());
    _chooedUser.addAll(widget.choosedUsers.toList());
    _chooedUser.addAll(chooedUser.toList());
    if (_chooedUser.length > 3) {
      for (int i = 0; i < 3; i++) {
        User friend = _chooedUser[i];
        groupName += friend.displayName + "、";
      }
    } else {
      for (User friend in _chooedUser) {
        groupName += friend.displayName + "、";
      }
    }
    groupName = groupName.substring(0, groupName.length - 1);
    List<String> userIds = _chooedUser.map((user) => user.uid).toList();
    File f =
        await getImageFileFromAssets('assets/images/default_nor_avatar.png');
    String defaultAvatar = f.path;
    try {
      String groupId = await FlutterWildfire.createGroup(
          groupName,
          userIds,
          [0],
          _chooedUser.map((user) {
            if (user.portrait != null && user.portrait.isNotEmpty) {
              return user.portrait;
            }
            return defaultAvatar;
          }).toList(),
          defaultAvatar);
      toast('创建群组成功');
      Map result = await FlutterWildfire.getGroupInfo(groupId);
      Group group = Group.fromJson(result);
      group.name = groupName;
      group.memberCount = userIds.length + 1;
      group.owner = Global.profile.user.uid;
      try {
        await FlutterWildfire.clearUnreadStatus('Goup', groupId, 0);
      } finally {
        Navigator.of(context).pop();
        Navigator.of(context).pop();
        Navigator.of(context).pop();
        await Navigator.of(context)
            .push(new MaterialPageRoute(builder: (context) {
          return GroupMessagesPage(groupInfo: group);
        }));
      }
    } catch (e) {
      print(e);
    }
  }

  @override
  Widget build(BuildContext context) {
    final List<Widget> _body = [
      ListView.builder(
        controller: _scrollController,
        itemBuilder: (BuildContext context, int index) {
          if (index < _functionButtons.length) {
            return _functionButtons[index];
          }
          int _contactIndex = index - _functionButtons.length;
          bool _isGroupTitle = true;
          Contact _contact = _contacts[_contactIndex];
          if (_contactIndex >= 1 &&
              _contact.nameIndex == _contacts[_contactIndex - 1].nameIndex) {
            _isGroupTitle = false;
          }

          return _ContactItem(
              disabled: _contact.disabled,
              choosed: chooedUser.any((user) => user.uid == _contact.user.uid),
              onPressed: _contact.disabled
                  ? null
                  : () async {
                      int index = chooedUser
                          .indexWhere((user) => user.uid == _contact.user.uid);
                      if (index > -1) {
                        chooedUser.removeAt(index);
                      } else {
                        chooedUser.add(_contact.user);
                      }
                      this.setState(() {});
                    },
              avatar: _contact.avatar != null && _contact.avatar.isNotEmpty
                  ? _contact.avatar
                  : 'assets/images/default_nor_avatar.png',
              title: _contact.name,
              groupTitle: _isGroupTitle ? _contact.nameIndex : null);
        },
        itemCount: _contacts.length + _functionButtons.length,
      ),
      Positioned(
        width: Constants.IndexBarWidth,
        right: 0.0,
        top: 0.0,
        bottom: 0.0,
        child: Container(
          color: widget._indexBarBg,
          child: LayoutBuilder(
            builder: _buildIndexBar,
          ),
        ),
      ),
    ];
    if (widget._currentLetter != null && widget._currentLetter.isNotEmpty) {
      _body.add(
        Center(
          child: Container(
            width: Constants.IndexLetterBoxSize,
            height: Constants.IndexLetterBoxSize,
            decoration: BoxDecoration(
              color: AppColors.IndexLetterBoxBg,
              borderRadius: BorderRadius.all(
                  Radius.circular(Constants.IndexLetterBoxRadius)),
            ),
            child: Center(
              child: Text(widget._currentLetter,
                  style: AppStyles.IndexLetterBoxTextStyle),
            ),
          ),
        ),
      );
    }
    bool btnDisabled = false;
    if (chooedUser.length < 1) {
      btnDisabled = true;
    } else {
      bool _c1 = chooedUser.every((User cUser) =>
          widget.excludeUsers.any((User eUser) => eUser.uid == cUser.uid));
      bool _c2 = widget.excludeUsers.every((User eUser) =>
          chooedUser.any((User cUser) => eUser.uid == cUser.uid));
      btnDisabled = _c1 && _c2;
    }

    return Scaffold(
      appBar: AppBar(
        centerTitle: true,
        actions: <Widget>[
          Padding(
            padding: const EdgeInsets.all(8.0),
            child: MaterialButton(
              disabledColor: Colors.green.withAlpha(80),
              minWidth: 50.0,
              onPressed: btnDisabled
                  ? null
                  : (widget.group != null ? addGroupMembers : createGroup),
              color: Colors.green,
              child: Text(
                '完成(${chooedUser.length})',
                style: TextStyle(fontSize: 16.0, color: Colors.white),
              ),
            ),
          )
        ],
        title: Text(
          '选择联系人',
          style: TextStyle(
              fontSize: 16.0, color: Theme.of(context).iconTheme.color),
        ),
        leading: InkWell(
          child: Container(
            height: double.infinity,
            padding: EdgeInsets.symmetric(horizontal: 12.0),
            child: Center(
              child: Text(
                '取消',
                style: TextStyle(
                    fontSize: 16.0, color: Theme.of(context).iconTheme.color),
              ),
            ),
          ),
          onTap: () {
            Navigator.of(context).pop();
          },
        ),
      ),
      body: Column(
        children: <Widget>[
          Container(
            padding: EdgeInsets.symmetric(vertical: 12.0),
            width: double.infinity,
            height: 60.0,
            child: SingleChildScrollView(
              scrollDirection: Axis.horizontal,
              child: Wrap(
                // mainAxisAlignment: MainAxisAlignment.start,
                children: List.generate(chooedUser.length, (index) {
                  User user = chooedUser[index];
                  return Padding(
                    padding: EdgeInsets.symmetric(horizontal: 12.0),
                    child: ClipRRect(
                        borderRadius:
                            BorderRadius.circular(Constants.AvatarRadius),
                        child: myAvatar(user.portrait, size: 40.0)),
                  );
                }),
              ),
            ),
          ),
          Expanded(
            child: Stack(
              children: _body,
            ),
          )
        ],
      ),
    );
  }
}
